import numpy as np
a = np.array([i for i in range(1,10)]).reshape(3,3)
b = [1, 1, 1]
print(a)
print(b)
[[1 2 3] [4 5 6] [7 8 9]] [1, 1, 1]
c = a + b
print(c) #Remember this Value!
[[ 2 3 4] [ 5 6 7] [ 8 9 10]]
# The above broadcasting is equivalent to the following
d = np.empty_like(a)
print(d)
for i in range(3):
d[i , :] = a[i , : ] + b
print(d)
[[0 0 0] [0 0 0] [0 0 0]] [[ 2 3 4] [ 5 6 7] [ 8 9 10]]
# The above broadcasting is also equivalent to the following
b_modified = np.tile(b, (3, 1)) # Stack 3 copies of b on top of each other
c = a + b_modified
print(b_modified)
print(c)
[[1 1 1] [1 1 1] [1 1 1]] [[ 2 3 4] [ 5 6 7] [ 8 9 10]]
Broadcasting follows a strict set of rules to determine the interaction between two arrays:
Rule 1: If the two arrays differ in their number of dimensions, the shape of the one with fewer dimensions is padded with ones on its leading (left) side.
Rule 2: If the shape of the two arrays does not match in any dimension, the array with shape equal to 1 in that dimension is stretched to match the other shape.
Rule 3: If in any dimension, the sizes disagree and neither is equal to 1, an error is raised.
M = np.ones((2, 3))
a = np.arange(3)
print(M)
[[1. 1. 1.] [1. 1. 1.]]
print(a)
[0 1 2]
print(M.shape)
print(a.shape)
(2, 3) (3,)
We see by rule 1 that the array a has fewer dimensions, so we pad it on the left with ones:
M.shape = (2, 3)
a.shape = (1, 3)
By rule 2, we now see that the first dimension disagrees, so we stretch this dimension to match, and then two arrays can be added:
M.shape = (2, 3)
a.shape = (2, 3)
result = M + a
print( result )
print(result.shape)
[[1. 2. 3.] [1. 2. 3.]] (2, 3)

# shape (3,2) + shape(3,) addition
M = np.ones((3, 2))
a = np.arange(3)
print(a.shape)
(3,)
print(a[:, np.newaxis].shape)
result = M + a[:, np.newaxis]
print(result)
(3, 1) [[1. 1.] [2. 2.] [3. 3.]]